package com.joyoung.sweep.utils.blue;

import android.text.TextUtils;

import java.nio.ByteBuffer;

public class PackUtil {

    protected final static char[] hexArray = "0123456789ABCDEF".toCharArray();

    public final static int S_SSID_MAX_LENGTH = 32;
    public final static int S_PASSWORD_MAX_LENGTH = 64;


    /**
     * 将字符串转换成字节数组，为空时返回空字节
     *
     * @param text 字符串
     * @return 字节数组，为空时为byte[0]
     */
    public static byte[] getBytes(String text) {
        return TextUtils.isEmpty(text) ? new byte[0] : text.getBytes();
    }

    /**
     * 将字符串转换成字节数组，为空时返回空字节，大于指定长度则截取前面最大长度部分
     *
     * @param text      字符串
     * @param maxLength 允许返回的最大长度，超过则截取
     * @return 字节数组，为空时为byte[0]
     */
    public static byte[] getBytes(String text, int maxLength) {
        if (TextUtils.isEmpty(text)) {
            return new byte[0];
        }
        byte[] data = text.getBytes();
        if (data.length > maxLength) {
            byte[] out = new byte[maxLength];
            System.arraycopy(data, 0, out, 0, maxLength);
            return out;
        }
        return data;
    }


    public static byte bytesXor(byte[] data, int start, int end) {
        int sum = 0;
        for (int i = start; i < end; ++i) {
            sum ^= data[i];
        }
        return (byte) sum;
    }

    public static byte bytesAnd(byte[] data, int start, int end) {
        int sum = 0;
        for (int i = start; i < end; ++i) {
            sum += data[i];
        }
        return (byte) ((~sum+1) & 0xFF);
    }

    public static String bytesToHex(byte[] bytes) {
        char[] hexChars = new char[bytes.length * 2];
        for (int j = 0; j < bytes.length; j++) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }
        return new String(hexChars);
    }

    public static String bytesToHex2(byte[] bytes) {
        char[] hexChars = new char[bytes.length * 3 - 1];
        for (int j = 0; j < bytes.length; j++) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 3] = hexArray[v >>> 4];
            hexChars[j * 3 + 1] = hexArray[v & 0x0F];
            if (j != bytes.length - 1) hexChars[j * 3 + 2] = ' ';
        }
        return new String(hexChars);
    }

    /**
     * 生成完整透传协议字节数组，即蓝牙数据包的Data部分（蓝牙包封装时可能会切片）
     *
     * @param ssid     设备要连接的Wi-Fi SSID，最长32字节
     * @param password 设备要连接的Wi-Fi 秘钥，最长64字节
     * @return 完整透传协议字节数组
     */
    public static byte[] getSerialPack(String ssid, String password) {
        // 透传协议相关长度
        final int S_HEADER_LENGTH = 10;
        final int S_CRC_SUM_LENGTH = 1;
        final int S_ORDER_LENGTH = 2;

        // 透传协议头0xFAFB
        byte[] sHeader = new byte[2];
        sHeader[0] = (byte) (0xFA & 0xFF);
        sHeader[1] = (byte) (0xFB & 0xFF);

        // 透传协议版本，默认0x00
        byte[] sVersion = new byte[1];

        // 透传协议控制字 0x00:主动发送指令要求对方回复; 0x80:返回指令; 0x40:主动发送无需对方回复
        byte[] sControl = new byte[1];
        sControl[0] = (byte) (0x40 & 0xFF);

        // 透传协议指令
        byte[] order = new byte[S_ORDER_LENGTH];
        // 配网指令0x0001
        order[0] = (byte) (0xDE & 0xFF);
        order[1] = (byte) (0x01 & 0xFF);

        // SSID，SSID长度须≤32
        byte[] ssidBytes = getBytes(ssid, S_SSID_MAX_LENGTH);
        int ssidLength = ssidBytes.length;

        // 密码，Password长度须≤64
        byte[] passwordBytes = getBytes(password, S_PASSWORD_MAX_LENGTH);
        int passwordLength = passwordBytes.length;

        // 透传协议数据长度
        byte[] sDataLength = new byte[2];
        int iSDataLength = 1 + ssidLength + 1 + passwordLength;
        sDataLength[0] = (byte) ((iSDataLength >> 8) & 0xff);
        sDataLength[1] = (byte) (iSDataLength & 0xff);

        // 透传协议帧总数，预留，默认0x00
        byte[] sFrameCount = new byte[1];

        // 透传协议帧序号，预留，默认0x00
        byte[] sFrameSeq = new byte[1];

        // 透传协议校验，延迟生成透传协议的校验和，见下方代码
        byte[] sCrcSum = new byte[1];

        // 将透传协议组装成蓝牙协议的data
        int sTotalLength = S_HEADER_LENGTH + iSDataLength + S_CRC_SUM_LENGTH;
        ByteBuffer buffer = ByteBuffer.allocate(sTotalLength);
        buffer.put(sHeader);
        buffer.put(sVersion);
        buffer.put(sFrameCount);
        buffer.put(sFrameSeq);
        buffer.put(sControl);
        buffer.put(order);
        buffer.put(sDataLength);
        buffer.put((byte) (ssidLength & 0xFF));
        if (ssidLength > 0) {
            buffer.put(ssidBytes);
        }
        buffer.put((byte) (passwordLength & 0xFF));
        if (passwordLength > 0) {
            buffer.put(passwordBytes);
        }
        buffer.put(sCrcSum);

        byte[] data = buffer.array();
        if (data.length > 0) {
            // 延迟生成透传协议的校验和!!!
            data[data.length - 1] = PackUtil.bytesAnd(data, 0, data.length);
        }
        return data;
    }

    /**
     * 生成UDP 设备发现数据包<br/>
     * 如：<code>CC 00 00 01 00 00 07 00 00 01 DD 01 00 00</code>
     *
     * @return 字节数组
     */
    public static byte[] getDeviceFindUdpPack() {
        // CC 00 00 01 00 00 07 00 00 01 DD 01 00 00
        byte[] data = new byte[14];
        int i = 0;
        data[i++] = (byte) (0xCC & 0xFF);
        data[i++] = (byte) 0x00;
        data[i++] = (byte) 0x00;
        data[i++] = (byte) (0x01 & 0xFF);
        data[i++] = (byte) 0x00;
        data[i++] = (byte) 0x00;
        data[i++] = (byte) (0x07 & 0xFF);
        data[i++] = (byte) 0x00;
        data[i++] = (byte) 0x00;
        data[i++] = (byte) (0x01 & 0xFF);
        data[i++] = (byte) (0xDD & 0xFF);
//        data[i++] = (byte) (0x01 & 0xFF);
        // TODO: 2019/9/18  为防止局域网重复发现，暂时测试使用DD02
        data[i++] = (byte) (0x02 & 0xFF);
        data[i++] = (byte) 0x00;
        data[i] = (byte) 0x00;
        return data;
    }
}
